/**
 * <b>项目名称：</b>网络应用框架<br/>
 * <b>包    名：</b>com.hhwy.framework.persistent.impl<br/>
 * <b>文 件 名：</b>EntityHelper.java<br/>
 * <b>版本信息：</b><br/>
 * <b>日    期：</b>2016年6月20日-下午3:22:50<br/>
 * <b>Copyright (c)</b> 2016恒华伟业科技股份有限公司-版权所有<br/>
 *
 */
package com.hhwy.framework.persistent;

import com.hhwy.framework.configure.ConfigHelper;
import com.hhwy.framework.util.PlatformTools;
import org.apache.commons.lang3.CharUtils;
import org.apache.ibatis.jdbc.SqlBuilder;

import javax.persistence.Column;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <b>类 名 称：</b>EntityHelper<br/>
 * <b>类 描 述：</b><br/>
 * <b>创 建 人：</b>lihuiming<br/>
 * <b>修 改 人：</b>lhm<br/>
 * <b>修改时间：</b>2016年6月20日 下午3:22:50<br/>
 * <b>修改备注：</b><br/>
 *
 * @version 1.0.0<br/>
 */
public class EntityHelper extends SqlBuilder {

	Object entity;
	String id = null;
	List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
	StringBuilder setClause = new StringBuilder();
	StringBuilder fields = new StringBuilder();
	StringBuilder values = new StringBuilder();
	StringBuilder whereClause = new StringBuilder();
	Map<String, Object> valueMap = new HashMap<String, Object>();
	Field[] allFields = null;
	boolean excludeNull = false;
	String dbType = ConfigHelper.getConfig("hibernate.database");

	public EntityHelper(Object entity) {

		this.entity = entity;
	}

	/**
	 * 创建一个新的EntityHelper.java实例 EntityHelper.
	 *
	 * @param entity
	 * @param excludeNull
	 */

	public EntityHelper(Object entity, boolean excludeNull) {
		this.entity = entity;
		this.excludeNull = excludeNull;
	}

	public String getInsert(){
		getFields();
		BEGIN();
		INSERT_INTO(getTableName());
		if("MYSQL".equals(dbType)){
			for (FieldInfo field : fieldList) {
				VALUES("`"+field.getName()+"`",
						"#{" + field.getName() + getTypeInfo(field.getType()) + "}");
			}
		}else{
			for (FieldInfo field : fieldList) {
				VALUES(field.getName(),
						"#{" + field.getName() + getTypeInfo(field.getType()) + "}");
			}
		}
		return SQL();
	}

	public String getUpdate(){
		getFields();
		BEGIN();
		UPDATE(getTableName());
		SET(getSetClause());
		WHERE(getWhereClause());
		return SQL();
	}

	/**
	 * getTypeInfo: 指定特定的转换类型<br/>
	 *
	 * @param type
	 * @return String
	 * @exception
	 * @since 1.0.0
	 */
	private String getTypeInfo(Class type) {
		if (type.isAssignableFrom(Long.class)) {
			return ", javaType=long,jdbcType=VARCHAR";
		}
		return "";
	}

	/**
	 * getTableName: 获取表名<br/>
	 *
	 * @return String
	 * @exception
	 * @since 1.0.0
	 */
	public String getTableName() {
		String tableName = null;
		Table tableAnno = entity.getClass().getAnnotation(Table.class);
		if (tableAnno == null)
			return null;

		tableName = tableAnno.name();

		return tableName;
	}

	/**
	 * getFields: 获取插入的字段列表<br/>
	 *
	 * @return String
	 * @exception
	 * @since 1.0.0
	 */
	public String getFields() {

		if (fields.length() == 0) {

			getAllFields();
			for (Field field : allFields) {
				Column column = field.getAnnotation(Column.class);
				if (column == null)
					continue;

				if ("serialVersionUID".equals(field.getName()))
					continue;

				Object value = getValue(field.getName() , field.getType());
				//单位编号
				if("orgNo".equals(field.getName())){
					if(value == null){
						//value = getOrgNo();
					}
				}
				if ("id".equals(field.getName())) {
					if (value == null)
						value = PlatformTools.getID();
					id = String.valueOf(value);
				}

				if (value != null) {
					fieldList.add(new FieldInfo(column.name(), field
							.getType()));
					fields.append(column.name());
					values.append("#{").append(column.name()).append("}").append(",");
					valueMap.put(column.name(), value);

				}
			}
		}
		return fields.substring(0, fields.length() - 1);
	}




	public String getValues() {

		return values.substring(0, values.length() - 1);
	}

	public String getId() {
		if(id != null)
			return id;
		else
			return (String)getValue("id" , String.class);
	}
	public Map<String, Object> getValueMap() {

		return valueMap;
	}

	/**
	 * getValue: 描述这个方法的作用<br/>
	 *
	 * @param name
	 * @return String
	 * @exception
	 * @since 1.0.0
	 */
	private Object getValue(String name , Class fieldClass) {

		String methodName = getMethodName(name , fieldClass);
		Object result = null;
		try {
			Method m = getDeclaredMethod(methodName);
			if (m != null)
				result = m.invoke(entity);
		} catch (SecurityException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
		return result;
	}

	public Method getDeclaredMethod(String methodName,
									Class<?>... parameterTypes) {
		Method method = null;
		for (Class<?> clazz = entity.getClass(); clazz != Object.class; clazz = clazz
				.getSuperclass()) {
			try {
				method = clazz.getDeclaredMethod(methodName, parameterTypes);
				return method;
			} catch (Exception e) {
			}
		}
		return null;
	}

	private static String getMethodName(String name , Class fieldClass) {

		if(fieldClass == boolean.class){
			if(name.startsWith("is"))
				return name;
			else{
				String first = name.substring(0, 1);

				return "is"+ first.toUpperCase() + name.substring(1);
			}
		}
		if(name.length() > 1 && CharUtils.isAsciiAlphaUpper(name.charAt(1))){
			return "get" + name;
		}

		String first = name.substring(0, 1);
		return "get" + first.toUpperCase() + name.substring(1);
	}

	/**
	 * getFields: 获取实体的全部字段，包括实体超类（Domain)的字段<br/>
	 *
	 * @return Field []
	 * @exception
	 * @since 1.0.0
	 */
	private void getAllFields() {
		if (allFields != null)
			return;

		Field[] selfFields = entity.getClass().getDeclaredFields();
		Field[] superFields = entity.getClass().getSuperclass()
				.getDeclaredFields();
		Field[] allFields = new Field[selfFields.length + superFields.length];
		System.arraycopy(selfFields, 0, allFields, 0, selfFields.length);
		System.arraycopy(superFields, 0, allFields, selfFields.length,
				superFields.length);
		this.allFields = allFields;
	}

	/**
	 * getSetClause: 获取更新子句<br/>
	 *
	 * @return String
	 * @throws Exception
	 * @exception
	 * @since 1.0.0
	 */
	public String getSetClause(){
		getAllFields();
		for (Field field : allFields) {

			if("createUser".equals(field.getName())
					|| "createTime".equals(field.getName())
					//跳过单位编号，单位编号只在插入是设值
					|| "orgNo".equals(field.getName()))
				continue;

			Object value = getValue(field.getName(), field.getType());
			if ("id".equals(field.getName())) {
				whereClause.append("id=").append("'").append(value).append("'");
			}
			Column column = field.getAnnotation(Column.class);
			if (column == null
					|| "serialVersionUID".equals(field.getName())
					|| "id".equals(field.getName()))
				continue;
			String tempString = null;
			if("MYSQL".equals(dbType)){
				tempString = "`"+column.name()+"`";
			}else{
				tempString = column.name();
			}
			if (value != null) {
				setClause.append(tempString).append("=").append("#{")
						.append(column.name())
						.append(getTypeInfo(field.getType())).append("}")
						.append(",");

				valueMap.put(column.name(), value);

				//如果不是调用排除空属性的方法，则更新为空
			}else if(!excludeNull){
				setClause.append(tempString).append("=").append("null")
						.append(",");
			}
		}
		return setClause.substring(0, setClause.length() - 1).toString();
	}

	/**
	 * getWhereClause: 获取条件子句<br/>
	 *
	 * @return String
	 * @exception
	 * @since 1.0.0
	 */
	public String getWhereClause() {
		if(whereClause.length() == 0)
			whereClause = new StringBuilder("id='").append(getValue("id" , String.class)).append("'");

		return whereClause.toString();
	}

	class FieldInfo {
		String name;
		Class type;

		public FieldInfo(String name, Class type) {
			this.name = name;
			this.type = type;
		}

		/**
		 * name
		 *
		 * @return the name
		 * @since 1.0.0
		 */

		public String getName() {
			return name;
		}

		/**
		 * @param name
		 *            the name to set
		 */

		public void setName(String name) {
			this.name = name;
		}

		/**
		 * type
		 *
		 * @return the type
		 * @since 1.0.0
		 */

		public Class getType() {
			return type;
		}

		/**
		 * @param type
		 *            the type to set
		 */

		public void setType(Class type) {
			this.type = type;
		}

	}

	public static void main(String[] args){
//		TodoTask tt = new TodoTask();
		/*MessageReceiver mr = new MessageReceiver();
		mr.setUserId("123");
		mr.setMessageId("111");
		mr.setRead(false);
		EntityHelper eh = new EntityHelper(mr);
		System.out.println(eh.getInsert());
		System.out.println(eh.getValueMap());*/
	}
	public static void mainx(String[] args) {
//		System.out.println(getMethodName("nmlhm"));
//		 TodoTask tt = new TodoTask();
//		 tt.setBusinessCode("123");
//		 tt.setBusinessCodeName("12222");
//		 tt.setBusinessDataId("11223");
//		 tt.setCreateTime(new Timestamp(new Date().getTime()));
//		 tt.setCreateUser("lhm");
//		 tt.setId(PlatformTools.getID());
//		 tt.setMemo("cesss");
//		 EntityHelper eh = new EntityHelper(tt);
//		System.out.println(eh.getFields());
//		System.out.println( eh.getTableName());
		// System.out.println("table==" + eh.getTableName());
		// System.out.println("fields==" + eh.getFields());
		// System.out.println("values==" + eh.getValues());
	}
}
